//
//  CZEmoticonManager.swift
//  004-表情包数据
//
//  Created by apple on 16/7/10.
//  Copyright © 2016年 itcast. All rights reserved.
//

import UIKit

/// 表情管理器
class CZEmoticonManager {
 //为了便于表情的复用 建立一个单例 只加载一次表情数据
    static let shared = CZEmoticonManager()
    //表情包的懒加载数组 第一个数组是最近表情 加载之后 表情数组为空
    lazy var packages = [CZEmoticonPackage]()
    //表情素材的bundle
    lazy var bundle:Bundle = {
     let path = Bundle.main.path(forResource: "HMEmoticon.bundle", ofType: nil)
        return Bundle(path: path!)!
    }()
    //构造函数 如果在init之前增加priviate 修饰符 可以要求调用者必须通过shared访问对象
    //OC要重写allocWithZONE方法
   private init() {
        loadPackages()
    }
    func recentEmoticon(em:CZEmoticon){
        //增加表情的使用次数
        em.times += 1
        
        //判断是否已经记录了该表情  如果没有记录 添加记录
        if !packages[0].emoticons.contains(em) {
            packages[0].emoticons.append(em)
        }
        //根据使用次数排序  使用次数高的排序靠前
        packages[0].emoticons.sort { (em1, em2) -> Bool in
            return em1.times > em2.times
        }
        //判断表情数组是否超出20  如果超出 删除末尾的表情
        if packages[0].emoticons.count > 20 {
            packages[0].emoticons .removeSubrange(20..<packages[0].emoticons.count)
        }
    }
}
//表情符号字符串的处理
extension CZEmoticonManager{
    
    /// 将给定的字符串 转化成属性文本
    ///关键点 要按照匹配结果倒叙替换属性文本 importantPoint
    /// - Parameter string: 完整的字符串
    /// - Returns: 属性文本
    func emoticonsString(string:String,font:UIFont) -> NSAttributedString {
        let attrString = NSMutableAttributedString(string: string)
        //1.建立正则表达式 过滤所有的表情文字
        //[] () 都是正则表达式的关键字 如果参与匹配 需要转义
        let pattern = "\\[.*?\\]"
        guard let regx = try? NSRegularExpression(pattern: pattern, options: []) else {
            return attrString
        }
        
        //2 匹配所有项
        let maches = regx.matches(in: string, options: [], range: NSRange(location: 0, length: attrString.length))
        //3遍历所有匹配结果
        for m in maches.reversed() {
            let r = m.range(at: 0)
            let subStr = (attrString.string as NSString).substring(with: r)
            //使用subStr查找对应的表情符号
            if  let em = CZEmoticonManager.shared.findEmoticon(string: subStr){
                
                //fix
                attrString.replaceCharacters(in: r, with: em.imageText(font: font))
                //可以使用表情符号中的属性文本 替换原有的属性文本 的内容
            }
        }
        //统一设置一遍字符串的属性
        //importantPoint生成的属性文本一定要全局替换字体 否则不完整会出错
        attrString.addAttributes([NSAttributedStringKey.font :font,NSAttributedStringKey.foregroundColor:UIColor.darkGray],range: NSRange(location: 0, length: attrString.length))
        return attrString
    }
    
    
    
    /// 根据string在所有的表情符号 中查找对应的表情模型对象
    ///如果找到 返回表情模型 否则返回nil
    func findEmoticon(string:String) -> CZEmoticon? {
        //1遍历表情包
        for p in packages {
            //在表情数组中过滤string[谓词]
            //OC中过滤素组使用谓词
            //方法1
//            let result = p.emoticons.filter({ (em) -> Bool in
//                return em.chs == string
//            })
            //方法2
//            let result = p.emoticons.filter(){ (em) -> Bool in
//                return em.chs == string
//            }
            //方法三 如果闭包中只有一句 并且返回
            //闭包格式可以省略
            //参数省略之后 使用$0 $1 依次替代原有的参数
//            let result = p.emoticons.filter(){
//                return $0.chs == string
//            }
            //方法四 return 也可以省略
            let result = p.emoticons.filter(){
                $0.chs == string
            }
            //判断结果数组的数量
            if result.count == 1{
                return result[0]
            }
        }
        return nil
    }
}

//表情包数据处理
private extension CZEmoticonManager{
    //读取Emoticon.plist
    
    func loadPackages() {
        //只要按照Bundle默认的目录结构设定 就可以直接读取其下的目录文件
        guard let path = Bundle.main.path(forResource: "HMEmoticon.bundle", ofType: nil),let bundle = Bundle(path: path), let plistPath = bundle.path(forResource: "emoticons.plist", ofType: nil),let array = NSArray(contentsOfFile: plistPath) as? [[String:String]],let model = NSArray.yy_modelArray(with: CZEmoticonPackage.self, json: array) as? [CZEmoticonPackage] else {
            return
        }
        //设置表情包数据
        //使用+=不需要再次给packages分配空间  直接追加数据
        packages += model
        
        
    }
    
}





























